Geo-Specific Visualization of Retail and Online Sales

library(ggmap)
Loading required package: ggplot2
Google Maps API Terms of Service: http://developers.google.com/maps/terms.
Please cite ggmap if you use it: see citation('ggmap') for details.
library(ggplot2)
library(zipcode)
data_dc <- read.delim(file='//10.8.8.51/lv0/Move to Box/Mithun/projects/9.BR_US_DS_Project/1.data/BR_disc_sens_geo_data.txt',
                      sep = '|',header = F, col.names = c('customer_key',
'percent_disc_last_12_mth',
'br_net_sales_amt_12_mth',
'flag_employee',
'addr_zip_code',
'resp_disc_percent',
'browse_hit_ind_tot',
'purchased',
'br_online_sales12_mth',
'br_offline_sales_12mth'))
data_dc$br_retail_percent <-  data_dc$br_offline_sales_12mth / data_dc$br_net_sales_amt_12_mth
data_dc$br_online_percent <-  data_dc$br_online_sales12_mth / data_dc$br_net_sales_amt_12_mth
data_dc$br_gross_sales_amt <-  data_dc$br_net_sales_amt_12_mth / (1 - data_dc$percent_disc_last_12_mth)

Plot Data as per PIN code

library(dplyr)

Attaching package: <U+393C><U+3E31>dplyr<U+393C><U+3E32>

The following objects are masked from <U+393C><U+3E31>package:stats<U+393C><U+3E32>:

    filter, lag

The following objects are masked from <U+393C><U+3E31>package:base<U+393C><U+3E32>:

    intersect, setdiff, setequal, union
zip_wise_data <- data_dc[,c("br_offline_sales_12mth","br_online_sales12_mth","br_net_sales_amt_12_mth","br_gross_sales_amt","addr_zip_code")] %>% group_by(addr_zip_code) %>% summarise(br_online_sales12_mth = sum(br_online_sales12_mth,na.rm=T), br_offline_sales_12mth = sum(br_offline_sales_12mth,na.rm=T), br_net_sales_amt_12_mth = sum(br_net_sales_amt_12_mth,na.rm=T), br_gross_sales_amt = sum(br_gross_sales_amt,na.rm=T))
zip_wise_data <- zip_wise_data[zip_wise_data$addr_zip_code!='',]
library(zipcode)
data("zipcode")
data_dc2<- inner_join(data_dc,zipcode,by=c("addr_zip_code"="zip"))
joining factor and character vector, coercing into character vector
library("ggplot2")
zip_wise_data <- left_join(zipcode,zip_wise_data,by=c("zip"="addr_zip_code"))
joining factor and character vector, coercing into character vector

Discount Rate by ZipCode

zip_wise_data$disc_percent <- (1 - zip_wise_data$br_net_sales_amt_12_mth/zip_wise_data$br_gross_sales_amt )
zip_wise_data$disc_percent[is.na(zip_wise_data$disc_percent)] <- 0
zip_wise_data$disc_percent[zip_wise_data$disc_percent > 1] <- 1
zip_wise_data$disc_percent[zip_wise_data$disc_percent < 0] <- 0
zip_wise_data$Online_percent<-zip_wise_data$br_online_sales12_mth/zip_wise_data$br_net_sales_amt_12_mth
zip_wise_data$Online_percent[is.na(zip_wise_data$Online_percent)] <- 0
zip_wise_data$Online_percent[zip_wise_data$Online_percent > 1] <- 1
zip_wise_data$Online_percent[zip_wise_data$Online_percent < 0] <- 0
zip_wise_data$binx <- cut(zip_wise_data$disc_percent,breaks = c(-Inf,0,0.20,0.35,0.40,Inf),include.lowest = T,
                          labels = c("No_Info","a_Low","b_Medium","c_High","d_VeryHigh"))
zip_wise_data <-zip_wise_data[which(zip_wise_data$latitude < 50 & zip_wise_data$latitude > 25 &
                                    zip_wise_data$longitude > -125 &  zip_wise_data$longitude < -66),]
ggplot(data=zip_wise_data) + geom_point(aes(x=longitude, y=latitude, colour=binx)) +ggtitle(" Discount Rate  ZIPCODE wise") +theme(legend.position ="bottom")

ggplot(zip_wise_data, aes(x = longitude, y = latitude,  fill= disc_percent )) + geom_polygon(colour = "white", size = 0.1) + theme(legend.position ="bottom")

ggplot(zip_wise_data, aes(x = longitude, y = latitude,  fill= Online_percent )) + geom_polygon(colour = "white", size = 0.1) + theme(legend.position ="bottom")

Discount Bin 10 is highest Discount

require(ggplot2)
require(maptools)
mapcounties <- map_data("county")
mapstates <- map_data("state")

counties <- map('county', fill=TRUE, col="transparent", plot=FALSE)
IDs <- sapply(strsplit(counties$names, ":"), function(x) x[1])
counties_sp <- map2SpatialPolygons(counties, IDs=IDs,
                                   proj4string=CRS("+proj=longlat +datum=WGS84"))

pointsSP <- SpatialPoints(as.data.frame(zip_wise_data[,c('longitude','latitude')]),
proj4string=CRS("+proj=longlat +datum=WGS84"))
indices <- over(pointsSP, counties_sp)

countyNames <- sapply(counties_sp@polygons, function(x) x@ID)

zip_wise_data$county<-countyNames[indices]
# Generate Comma Separated County/Subregion list for all Counties of US
#
mapcounties$county <- with(mapcounties , paste(region, subregion, sep = ","))

# Aggregate our data at County Level (it was earlier aggreated at zipcode level)
#
zip_wise_data.sum<- zip_wise_data %>% group_by(county) %>%  summarize(br_online_sales12_mth = sum(br_online_sales12_mth,na.rm=T), br_offline_sales_12mth = sum(br_offline_sales_12mth,na.rm=T), br_net_sales_amt_12_mth = sum(br_net_sales_amt_12_mth,na.rm=T), br_gross_sales_amt = sum(br_gross_sales_amt,na.rm=T),disc_percent=median(disc_percent,na.rm=T),Online_percent=median(Online_percent))


# Remove any duplicate records
#
zip_wise_data.un<-zip_wise_data.sum[!duplicated(zip_wise_data[c("county")]),]

zip_wise_data.final=merge(zip_wise_data.sum,zip_wise_data.un,by.x='county',by.y = 'county')

zip_wise_data.final$disc_perc_bin <- as.factor(ntile(zip_wise_data.final$disc_percent.x,5))
# Merge our data with all US counties data
#
zip_wise_data.final$Online_percent_bin <- as.factor(ntile(zip_wise_data.final$Online_percent.x,5))
mergedata <- merge(mapcounties, zip_wise_data.final, by.x = "county", by.y = "county")

High Discount Rate County Wise

High Online Sale Percent County Wise

Statewide map

zip_wise_data_state <- inner_join(st_code_file,zip_wise_data_state,by=c("state_code"="state"))
joining factor and character vector, coercing into character vector

Discount and % of Online Sales Visualization by State

% Online Sales by State

Discount Percent taken accross United States

Online Sale Percent over overall sales accross United States

LS0tDQp0aXRsZTogJyBHZW8gTG9jYXRpb24gV2lzZSBSZXRhaWwgYW5kIE9ubGluZSBTYWxlIFZpc3VhbGl6YXRpb24nDQpvdXRwdXQ6DQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdA0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KDQpHZW8tU3BlY2lmaWMgVmlzdWFsaXphdGlvbiBvZiBSZXRhaWwgYW5kIE9ubGluZSBTYWxlcw0KDQpgYGB7cn0NCmxpYnJhcnkoZ2dtYXApDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHppcGNvZGUpDQoNCmRhdGFfZGMgPC0gcmVhZC5kZWxpbShmaWxlPScvLzEwLjguOC41MS9sdjAvTW92ZSB0byBCb3gvTWl0aHVuL3Byb2plY3RzLzkuQlJfVVNfRFNfUHJvamVjdC8xLmRhdGEvQlJfZGlzY19zZW5zX2dlb19kYXRhLnR4dCcsDQogICAgICAgICAgICAgICAgICAgICAgc2VwID0gJ3wnLGhlYWRlciA9IEYsIGNvbC5uYW1lcyA9IGMoJ2N1c3RvbWVyX2tleScsDQoncGVyY2VudF9kaXNjX2xhc3RfMTJfbXRoJywNCidicl9uZXRfc2FsZXNfYW10XzEyX210aCcsDQonZmxhZ19lbXBsb3llZScsDQonYWRkcl96aXBfY29kZScsDQoncmVzcF9kaXNjX3BlcmNlbnQnLA0KJ2Jyb3dzZV9oaXRfaW5kX3RvdCcsDQoncHVyY2hhc2VkJywNCidicl9vbmxpbmVfc2FsZXMxMl9tdGgnLA0KJ2JyX29mZmxpbmVfc2FsZXNfMTJtdGgnKSkNCg0KZGF0YV9kYyRicl9yZXRhaWxfcGVyY2VudCA8LSAgZGF0YV9kYyRicl9vZmZsaW5lX3NhbGVzXzEybXRoIC8gZGF0YV9kYyRicl9uZXRfc2FsZXNfYW10XzEyX210aA0KDQpkYXRhX2RjJGJyX29ubGluZV9wZXJjZW50IDwtICBkYXRhX2RjJGJyX29ubGluZV9zYWxlczEyX210aCAvIGRhdGFfZGMkYnJfbmV0X3NhbGVzX2FtdF8xMl9tdGgNCg0KZGF0YV9kYyRicl9ncm9zc19zYWxlc19hbXQgPC0gIGRhdGFfZGMkYnJfbmV0X3NhbGVzX2FtdF8xMl9tdGggLyAoMSAtIGRhdGFfZGMkcGVyY2VudF9kaXNjX2xhc3RfMTJfbXRoKQ0KDQpgYGANClBsb3QgRGF0YSBhcyBwZXIgUElOIGNvZGUNCmBgYHtyfQ0KbGlicmFyeShkcGx5cikNCnppcF93aXNlX2RhdGEgPC0gZGF0YV9kY1ssYygiYnJfb2ZmbGluZV9zYWxlc18xMm10aCIsImJyX29ubGluZV9zYWxlczEyX210aCIsImJyX25ldF9zYWxlc19hbXRfMTJfbXRoIiwiYnJfZ3Jvc3Nfc2FsZXNfYW10IiwiYWRkcl96aXBfY29kZSIpXSAlPiUgZ3JvdXBfYnkoYWRkcl96aXBfY29kZSkgJT4lIHN1bW1hcmlzZShicl9vbmxpbmVfc2FsZXMxMl9tdGggPSBzdW0oYnJfb25saW5lX3NhbGVzMTJfbXRoLG5hLnJtPVQpLCBicl9vZmZsaW5lX3NhbGVzXzEybXRoID0gc3VtKGJyX29mZmxpbmVfc2FsZXNfMTJtdGgsbmEucm09VCksIGJyX25ldF9zYWxlc19hbXRfMTJfbXRoID0gc3VtKGJyX25ldF9zYWxlc19hbXRfMTJfbXRoLG5hLnJtPVQpLCBicl9ncm9zc19zYWxlc19hbXQgPSBzdW0oYnJfZ3Jvc3Nfc2FsZXNfYW10LG5hLnJtPVQpKQ0KDQp6aXBfd2lzZV9kYXRhIDwtIHppcF93aXNlX2RhdGFbemlwX3dpc2VfZGF0YSRhZGRyX3ppcF9jb2RlIT0nJyxdDQoNCg0KbGlicmFyeSh6aXBjb2RlKQ0KZGF0YSgiemlwY29kZSIpDQpkYXRhX2RjMjwtIGlubmVyX2pvaW4oZGF0YV9kYyx6aXBjb2RlLGJ5PWMoImFkZHJfemlwX2NvZGUiPSJ6aXAiKSkNCmxpYnJhcnkoImdncGxvdDIiKQ0KDQp6aXBfd2lzZV9kYXRhIDwtIGxlZnRfam9pbih6aXBjb2RlLHppcF93aXNlX2RhdGEsYnk9YygiemlwIj0iYWRkcl96aXBfY29kZSIpKQ0KYGBgDQpEaXNjb3VudCBSYXRlIGJ5IFppcENvZGUNCg0KYGBge3J9DQp6aXBfd2lzZV9kYXRhJGRpc2NfcGVyY2VudCA8LSAoMSAtIHppcF93aXNlX2RhdGEkYnJfbmV0X3NhbGVzX2FtdF8xMl9tdGgvemlwX3dpc2VfZGF0YSRicl9ncm9zc19zYWxlc19hbXQgKQ0KemlwX3dpc2VfZGF0YSRkaXNjX3BlcmNlbnRbaXMubmEoemlwX3dpc2VfZGF0YSRkaXNjX3BlcmNlbnQpXSA8LSAwDQp6aXBfd2lzZV9kYXRhJGRpc2NfcGVyY2VudFt6aXBfd2lzZV9kYXRhJGRpc2NfcGVyY2VudCA+IDFdIDwtIDENCnppcF93aXNlX2RhdGEkZGlzY19wZXJjZW50W3ppcF93aXNlX2RhdGEkZGlzY19wZXJjZW50IDwgMF0gPC0gMA0KDQp6aXBfd2lzZV9kYXRhJE9ubGluZV9wZXJjZW50PC16aXBfd2lzZV9kYXRhJGJyX29ubGluZV9zYWxlczEyX210aC96aXBfd2lzZV9kYXRhJGJyX25ldF9zYWxlc19hbXRfMTJfbXRoDQp6aXBfd2lzZV9kYXRhJE9ubGluZV9wZXJjZW50W2lzLm5hKHppcF93aXNlX2RhdGEkT25saW5lX3BlcmNlbnQpXSA8LSAwDQp6aXBfd2lzZV9kYXRhJE9ubGluZV9wZXJjZW50W3ppcF93aXNlX2RhdGEkT25saW5lX3BlcmNlbnQgPiAxXSA8LSAxDQp6aXBfd2lzZV9kYXRhJE9ubGluZV9wZXJjZW50W3ppcF93aXNlX2RhdGEkT25saW5lX3BlcmNlbnQgPCAwXSA8LSAwDQoNCnppcF93aXNlX2RhdGEkYmlueCA8LSBjdXQoemlwX3dpc2VfZGF0YSRkaXNjX3BlcmNlbnQsYnJlYWtzID0gYygtSW5mLDAsMC4yMCwwLjM1LDAuNDAsSW5mKSxpbmNsdWRlLmxvd2VzdCA9IFQsDQogICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGMoIk5vX0luZm8iLCJhX0xvdyIsImJfTWVkaXVtIiwiY19IaWdoIiwiZF9WZXJ5SGlnaCIpKQ0KDQoNCnppcF93aXNlX2RhdGEgPC16aXBfd2lzZV9kYXRhW3doaWNoKHppcF93aXNlX2RhdGEkbGF0aXR1ZGUgPCA1MCAmIHppcF93aXNlX2RhdGEkbGF0aXR1ZGUgPiAyNSAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6aXBfd2lzZV9kYXRhJGxvbmdpdHVkZSA+IC0xMjUgJiAgemlwX3dpc2VfZGF0YSRsb25naXR1ZGUgPCAtNjYpLF0NCmdncGxvdChkYXRhPXppcF93aXNlX2RhdGEpICsgZ2VvbV9wb2ludChhZXMoeD1sb25naXR1ZGUsIHk9bGF0aXR1ZGUsIGNvbG91cj1iaW54KSkgK2dndGl0bGUoIiBEaXNjb3VudCBSYXRlICBaSVBDT0RFIHdpc2UiKSArdGhlbWUobGVnZW5kLnBvc2l0aW9uID0iYm90dG9tIikNCg0KZ2dwbG90KHppcF93aXNlX2RhdGEsIGFlcyh4ID0gbG9uZ2l0dWRlLCB5ID0gbGF0aXR1ZGUsICBmaWxsPSBkaXNjX3BlcmNlbnQgKSkgKyBnZW9tX3BvbHlnb24oY29sb3VyID0gIndoaXRlIiwgc2l6ZSA9IDAuMSkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSJib3R0b20iKQ0KDQpnZ3Bsb3QoemlwX3dpc2VfZGF0YSwgYWVzKHggPSBsb25naXR1ZGUsIHkgPSBsYXRpdHVkZSwgIGZpbGw9IE9ubGluZV9wZXJjZW50ICkpICsgZ2VvbV9wb2x5Z29uKGNvbG91ciA9ICJ3aGl0ZSIsIHNpemUgPSAwLjEpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0iYm90dG9tIikNCg0KYGBgDQpEaXNjb3VudCBCaW4gMTAgaXMgaGlnaGVzdCBEaXNjb3VudA0KYGBge3J9DQpyZXF1aXJlKGdncGxvdDIpDQpyZXF1aXJlKG1hcHRvb2xzKQ0KbWFwY291bnRpZXMgPC0gbWFwX2RhdGEoImNvdW50eSIpDQptYXBzdGF0ZXMgPC0gbWFwX2RhdGEoInN0YXRlIikNCg0KY291bnRpZXMgPC0gbWFwKCdjb3VudHknLCBmaWxsPVRSVUUsIGNvbD0idHJhbnNwYXJlbnQiLCBwbG90PUZBTFNFKQ0KSURzIDwtIHNhcHBseShzdHJzcGxpdChjb3VudGllcyRuYW1lcywgIjoiKSwgZnVuY3Rpb24oeCkgeFsxXSkNCmNvdW50aWVzX3NwIDwtIG1hcDJTcGF0aWFsUG9seWdvbnMoY291bnRpZXMsIElEcz1JRHMsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb2o0c3RyaW5nPUNSUygiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQiKSkNCg0KcG9pbnRzU1AgPC0gU3BhdGlhbFBvaW50cyhhcy5kYXRhLmZyYW1lKHppcF93aXNlX2RhdGFbLGMoJ2xvbmdpdHVkZScsJ2xhdGl0dWRlJyldKSwNCnByb2o0c3RyaW5nPUNSUygiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQiKSkNCmluZGljZXMgPC0gb3Zlcihwb2ludHNTUCwgY291bnRpZXNfc3ApDQoNCmNvdW50eU5hbWVzIDwtIHNhcHBseShjb3VudGllc19zcEBwb2x5Z29ucywgZnVuY3Rpb24oeCkgeEBJRCkNCg0KemlwX3dpc2VfZGF0YSRjb3VudHk8LWNvdW50eU5hbWVzW2luZGljZXNdDQojIEdlbmVyYXRlIENvbW1hIFNlcGFyYXRlZCBDb3VudHkvU3VicmVnaW9uIGxpc3QgZm9yIGFsbCBDb3VudGllcyBvZiBVUw0KIw0KbWFwY291bnRpZXMkY291bnR5IDwtIHdpdGgobWFwY291bnRpZXMgLCBwYXN0ZShyZWdpb24sIHN1YnJlZ2lvbiwgc2VwID0gIiwiKSkNCg0KIyBBZ2dyZWdhdGUgb3VyIGRhdGEgYXQgQ291bnR5IExldmVsIChpdCB3YXMgZWFybGllciBhZ2dyZWF0ZWQgYXQgemlwY29kZSBsZXZlbCkNCiMNCnppcF93aXNlX2RhdGEuc3VtPC0gemlwX3dpc2VfZGF0YSAlPiUgZ3JvdXBfYnkoY291bnR5KSAlPiUgIHN1bW1hcml6ZShicl9vbmxpbmVfc2FsZXMxMl9tdGggPSBzdW0oYnJfb25saW5lX3NhbGVzMTJfbXRoLG5hLnJtPVQpLCBicl9vZmZsaW5lX3NhbGVzXzEybXRoID0gc3VtKGJyX29mZmxpbmVfc2FsZXNfMTJtdGgsbmEucm09VCksIGJyX25ldF9zYWxlc19hbXRfMTJfbXRoID0gc3VtKGJyX25ldF9zYWxlc19hbXRfMTJfbXRoLG5hLnJtPVQpLCBicl9ncm9zc19zYWxlc19hbXQgPSBzdW0oYnJfZ3Jvc3Nfc2FsZXNfYW10LG5hLnJtPVQpLGRpc2NfcGVyY2VudD1tZWRpYW4oZGlzY19wZXJjZW50LG5hLnJtPVQpLE9ubGluZV9wZXJjZW50PW1lZGlhbihPbmxpbmVfcGVyY2VudCkpDQoNCg0KIyBSZW1vdmUgYW55IGR1cGxpY2F0ZSByZWNvcmRzDQojDQp6aXBfd2lzZV9kYXRhLnVuPC16aXBfd2lzZV9kYXRhLnN1bVshZHVwbGljYXRlZCh6aXBfd2lzZV9kYXRhW2MoImNvdW50eSIpXSksXQ0KDQp6aXBfd2lzZV9kYXRhLmZpbmFsPW1lcmdlKHppcF93aXNlX2RhdGEuc3VtLHppcF93aXNlX2RhdGEudW4sYnkueD0nY291bnR5JyxieS55ID0gJ2NvdW50eScpDQoNCnppcF93aXNlX2RhdGEuZmluYWwkZGlzY19wZXJjX2JpbiA8LSBhcy5mYWN0b3IobnRpbGUoemlwX3dpc2VfZGF0YS5maW5hbCRkaXNjX3BlcmNlbnQueCw1KSkNCiMgTWVyZ2Ugb3VyIGRhdGEgd2l0aCBhbGwgVVMgY291bnRpZXMgZGF0YQ0KIw0KemlwX3dpc2VfZGF0YS5maW5hbCRPbmxpbmVfcGVyY2VudF9iaW4gPC0gYXMuZmFjdG9yKG50aWxlKHppcF93aXNlX2RhdGEuZmluYWwkT25saW5lX3BlcmNlbnQueCw1KSkNCm1lcmdlZGF0YSA8LSBtZXJnZShtYXBjb3VudGllcywgemlwX3dpc2VfZGF0YS5maW5hbCwgYnkueCA9ICJjb3VudHkiLCBieS55ID0gImNvdW50eSIpDQpgYGANCkhpZ2ggRGlzY291bnQgUmF0ZSBDb3VudHkgV2lzZQ0KYGBge3J9DQptYXAgPC0gZ2dwbG90KG1lcmdlZGF0YSwgYWVzKGxvbmcsbGF0LGdyb3VwPWdyb3VwKSkgKyBnZW9tX3BvbHlnb24oYWVzKGZpbGw9ZGlzY19wZXJjX2JpbikpIA0KbWFwIDwtIG1hcCt0aGVtZShwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGZpbGwgPSAid2hpdGUiKSxsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIiwNCiAgICAgICAgYXhpcy50aWNrcyA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF9ibGFuaygpKQ0KbWFwIDwtIG1hcCArIGdlb21fcGF0aChkYXRhID0gbWFwc3RhdGVzLCBjb2xvdXIgPSAiYmxhY2siLCBzaXplID0gLjMpDQptYXAgPC0gbWFwICsgZ2VvbV9wYXRoKGRhdGEgPSBtYXBjb3VudGllcywgY29sb3VyID0gInJlZCIsIHNpemUgPSAuNSwgYWxwaGEgPSAuMSkgICsNCiAgZXhwYW5kX2xpbWl0cyh4ID0gbWVyZ2VkYXRhJGxvbmcsIHkgPSBtZXJnZWRhdGEkbGF0KQ0KbWFwDQoNCg0KYGBgDQpIaWdoIE9ubGluZSBTYWxlIFBlcmNlbnQgQ291bnR5IFdpc2UNCg0KYGBge3J9DQpnZ3Bsb3QobWVyZ2VkYXRhLCBhZXMobG9uZyxsYXQsZ3JvdXA9Z3JvdXApKSArIGdlb21fcG9seWdvbihhZXMoZmlsbD1PbmxpbmVfcGVyY2VudF9iaW4pKSArIHRoZW1lKHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbCA9ICJ3aGl0ZSIpLGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLA0KICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCkpICsgZ2VvbV9wYXRoKGRhdGEgPSBtYXBzdGF0ZXMsIGNvbG91ciA9ICJibGFjayIsIHNpemUgPSAuMykgKyBnZW9tX3BhdGgoZGF0YSA9IG1hcGNvdW50aWVzLCBjb2xvdXIgPSAicmVkIiwgc2l6ZSA9IC41LCBhbHBoYSA9IC4xKSAgKw0KICBleHBhbmRfbGltaXRzKHggPSBtZXJnZWRhdGEkbG9uZywgeSA9IG1lcmdlZGF0YSRsYXQpDQoNCmBgYA0KU3RhdGV3aWRlIG1hcA0KYGBge3J9DQoNCnN0YXRlc19tYXAgPC1tYXBfZGF0YSgic3RhdGUiKQ0KaGVhZChzdGF0ZXNfbWFwKQ0KbGlicmFyeShzcWxkZikNCg0KZGF0YV9kYzMgPC0gIGxlZnRfam9pbih6aXBjb2RlWyxjKCJ6aXAiLCJzdGF0ZSIpXSxkYXRhX2RjMixieT1jKCJ6aXAiPSJhZGRyX3ppcF9jb2RlIikpDQoNCnJlcXVpcmUoZHBseXIpDQp6aXBfd2lzZV9kYXRhX3N0YXRlIDwtIGRhdGFfZGMyICU+JSBncm91cF9ieShzdGF0ZSkgJT4lIHN1bW1hcmlzZShicl9vbmxpbmVfc2FsZXMxMl9tdGggPSBzdW0oYnJfb25saW5lX3NhbGVzMTJfbXRoLG5hLnJtPVQpLCBicl9vZmZsaW5lX3NhbGVzXzEybXRoID0gc3VtKGJyX29mZmxpbmVfc2FsZXNfMTJtdGgsbmEucm09VCksIGJyX25ldF9zYWxlc19hbXRfMTJfbXRoID0gc3VtKGJyX25ldF9zYWxlc19hbXRfMTJfbXRoLG5hLnJtPVQpLCBicl9ncm9zc19zYWxlc19hbXQgPSBzdW0oYnJfZ3Jvc3Nfc2FsZXNfYW10LG5hLnJtPVQpKQ0KDQpzdF9jb2RlX2ZpbGU8LSBkYXRhLmZyYW1lKGZ1bGxfbmFtZT1jKCdhbGFiYW1hJywnYWxhc2thJywnYXJpem9uYScsJ2Fya2Fuc2FzJywnY2FsaWZvcm5pYScsJ2NvbG9yYWRvJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2Nvbm5lY3RpY3V0JywJJ2RlbGF3YXJlJywJJ2Rpc3RyaWN0IG9mIGNvbHVtYmlhJywJJ2Zsb3JpZGEnLAknZ2VvcmdpYScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdoYXdhaWknLAknaWRhaG8nLAknaWxsaW5vaXMnLAknaW5kaWFuYScsCSdpb3dhJywJJ2thbnNhcycsCSdrZW50dWNreScsCQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbG91aXNpYW5hJywJJ21haW5lJywJJ21hcnlsYW5kJywJJ21hc3NhY2h1c2V0dHMnLAknbWljaGlnYW4nLAknbWlubmVzb3RhJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ21pc3Npc3NpcHBpJywJJ21pc3NvdXJpJywJJ21vbnRhbmEnLAknbmVicmFza2EnLAknbmV2YWRhJywJJ25ldyBoYW1wc2hpcmUnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbmV3IGplcnNleScsCSduZXcgbWV4aWNvJywJJ25ldyB5b3JrJywJJ25vcnRoIGNhcm9saW5hJywJJ25vcnRoIGRha290YScsCQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnb2hpbycsCSdva2xhaG9tYScsCSdvcmVnb24nLAkncGVubnN5bHZhbmlhJywJJ3Job2RlIGlzbGFuZCcsCSdzb3V0aCBjYXJvbGluYScsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdzb3V0aCBkYWtvdGEnLAkndGVubmVzc2VlJywJJ3RleGFzJywJJ3V0YWgnLAkndmVybW9udCcsCSd2aXJnaW5pYScsCSd3YXNoaW5ndG9uJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ3dlc3QgdmlyZ2luaWEnLAknd2lzY29uc2luJywJJ3d5b21pbmcnKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdGVfY29kZT1jKCdBTCcsCSdBSycsCSdBWicsCSdBUicsCSdDQScsCSdDTycsCSdDVCcsCSdERScsCSdEQycsCSdGTCcsCSdHQScsCSdISScsCSdJRCcsCSdJTCcsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnSU4nLAknSUEnLAknS1MnLAknS1knLAknTEEnLAknTUUnLAknTUQnLAknTUEnLAknTUknLAknTU4nLAknTVMnLAknTU8nLAknTVQnLAknTkUnLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ05WJywJJ05IJywJJ05KJywJJ05NJywJJ05ZJywJJ05DJywJJ05EJywJJ09IJywJJ09LJywJJ09SJywJJ1BBJywJJ1JJJywJJ1NDJywJJ1NEJywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdUTicsCSdUWCcsCSdVVCcsCSdWVCcsCSdWQScsCSdXQScsCSdXVicsCSdXSScsCSdXWScpKQ0KDQp6aXBfd2lzZV9kYXRhX3N0YXRlIDwtIGlubmVyX2pvaW4oc3RfY29kZV9maWxlLHppcF93aXNlX2RhdGFfc3RhdGUsYnk9Yygic3RhdGVfY29kZSI9InN0YXRlIikpDQoNCnppcF93aXNlX2RhdGFfc3RhdGUkZGlzY19wZXJjZW50IDwtICgxIC0gemlwX3dpc2VfZGF0YV9zdGF0ZSRicl9uZXRfc2FsZXNfYW10XzEyX210aC96aXBfd2lzZV9kYXRhX3N0YXRlJGJyX2dyb3NzX3NhbGVzX2FtdCApDQp6aXBfd2lzZV9kYXRhX3N0YXRlJGRpc2NfcGVyY2VudFtpcy5uYSh6aXBfd2lzZV9kYXRhX3N0YXRlJGRpc2NfcGVyY2VudCldIDwtIDANCnppcF93aXNlX2RhdGFfc3RhdGUkZGlzY19wZXJjZW50W3ppcF93aXNlX2RhdGFfc3RhdGUkZGlzY19wZXJjZW50ID4gMV0gPC0gMQ0KemlwX3dpc2VfZGF0YV9zdGF0ZSRkaXNjX3BlcmNlbnRbemlwX3dpc2VfZGF0YV9zdGF0ZSRkaXNjX3BlcmNlbnQgPCAwXSA8LSAwDQoNCnppcF93aXNlX2RhdGFfc3RhdGUkT25saW5lX3BlcmNlbnQgPC0gemlwX3dpc2VfZGF0YV9zdGF0ZSRicl9vbmxpbmVfc2FsZXMxMl9tdGgvemlwX3dpc2VfZGF0YV9zdGF0ZSRicl9uZXRfc2FsZXNfYW10XzEyX210aA0KemlwX3dpc2VfZGF0YV9zdGF0ZSRPbmxpbmVfcGVyY2VudFtpcy5uYSh6aXBfd2lzZV9kYXRhX3N0YXRlJE9ubGluZV9wZXJjZW50KV0gPC0gMA0KemlwX3dpc2VfZGF0YV9zdGF0ZSRPbmxpbmVfcGVyY2VudFt6aXBfd2lzZV9kYXRhX3N0YXRlJE9ubGluZV9wZXJjZW50ID4gMV0gPC0gMQ0KemlwX3dpc2VfZGF0YV9zdGF0ZSRPbmxpbmVfcGVyY2VudFt6aXBfd2lzZV9kYXRhX3N0YXRlJE9ubGluZV9wZXJjZW50IDwgMF0gPC0gMA0KDQoNCmBgYA0KIERpc2NvdW50IGFuZCAlIG9mIE9ubGluZSBTYWxlcyBWaXN1YWxpemF0aW9uIGJ5IFN0YXRlIA0KYGBge3J9DQp6aXBfd2lzZV9kYXRhX3N0YXRlMiA8LSB6aXBfd2lzZV9kYXRhX3N0YXRlWyxjKCJmdWxsX25hbWUiLCJkaXNjX3BlcmNlbnQiLCJPbmxpbmVfcGVyY2VudCIpXQ0KbmFtZXMoemlwX3dpc2VfZGF0YV9zdGF0ZTIpIDwtIGMoInN0YXRlIiwiZGlzY19wZXJjZW50IiwiT25saW5lX3BlcmNlbnQiKQ0KDQoNCmdncGxvdCh6aXBfd2lzZV9kYXRhX3N0YXRlMiwgYWVzKG1hcF9pZCA9IHN0YXRlKSkgKw0KICBnZW9tX21hcChhZXMoZmlsbCA9IGRpc2NfcGVyY2VudCksIG1hcCA9IHN0YXRlc19tYXAsIGNvbG9yID0iYmxhY2siKSArDQogIGV4cGFuZF9saW1pdHMoeCA9IHN0YXRlc19tYXAkbG9uZywgeSA9IHN0YXRlc19tYXAkbGF0KSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLA0KICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCkpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3c9ImdyZWVuIiwgaGlnaD0icmVkIikgKw0KICBndWlkZXMoZmlsbCA9IGd1aWRlX2NvbG9yYmFyKGJhcndpZHRoID0gMTAsIGJhcmhlaWdodCA9IDEpKQ0KYGBgDQolIE9ubGluZSBTYWxlcyBieSBTdGF0ZQ0KYGBge3J9DQpnZ3Bsb3QoemlwX3dpc2VfZGF0YV9zdGF0ZTIsIGFlcyhtYXBfaWQgPSBzdGF0ZSkpICsNCiAgZ2VvbV9tYXAoYWVzKGZpbGwgPSBPbmxpbmVfcGVyY2VudCksIG1hcCA9IHN0YXRlc19tYXAsIGNvbG9yID0iYmxhY2siKSArDQogIGV4cGFuZF9saW1pdHMoeCA9IHN0YXRlc19tYXAkbG9uZywgeSA9IHN0YXRlc19tYXAkbGF0KSArDQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iLA0KICAgICAgICBheGlzLnRpY2tzID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X2JsYW5rKCkpICsNCiAgc2NhbGVfZmlsbF9ncmFkaWVudChsb3c9ImdyZWVuIiwgaGlnaD0icmVkIikgDQogIGd1aWRlcyhmaWxsID0gZ3VpZGVfY29sb3JiYXIoYmFyd2lkdGggPSAxMCwgYmFyaGVpZ2h0ID0gLjUpKQ0KYGBgDQoNCkRpc2NvdW50ICBQZXJjZW50IHRha2VuIGFjY3Jvc3MgVW5pdGVkIFN0YXRlcw0KYGBge3J9DQpyZXF1aXJlKGxlYWZsZXQpDQoNCmxlYWZsZXQoemlwX3dpc2VfZGF0YSkgJT4lIGFkZFRpbGVzKCkgJT4lDQogIGFkZENpcmNsZXMobG5nID0gfmxvbmdpdHVkZSwgbGF0ID0gfmxhdGl0dWRlLCB3ZWlnaHQgPSAxLA0KICAgICAgICAgICAgIHJhZGl1cyA9IH4oZGlzY19wZXJjZW50LTAuMykqMTAwLCBwb3B1cCA9IH5jaXR5ICApDQpgYGANCg0KT25saW5lIFNhbGUgUGVyY2VudCBvdmVyIG92ZXJhbGwgc2FsZXMgYWNjcm9zcyBVbml0ZWQgU3RhdGVzDQoNCmBgYHtyfQ0KcmVxdWlyZShsZWFmbGV0KQ0KDQpsZWFmbGV0KHppcF93aXNlX2RhdGEpICU+JSBhZGRUaWxlcygpICU+JQ0KICBhZGRDaXJjbGVzKGxuZyA9IH5sb25naXR1ZGUsIGxhdCA9IH5sYXRpdHVkZSwgd2VpZ2h0ID0gMSwNCiAgICAgICAgICAgICByYWRpdXMgPSB+IChPbmxpbmVfcGVyY2VudC0wLjQpKjEwMCwgcG9wdXAgPSB+Y2l0eSAgLGNvbG9yID0gImdyZWVuIikNCmBgYA0KDQo=